#include "threadPool.h"

stack* stack_init() {
    stack* st = (stack*)calloc(1, sizeof(stack));
    if (!st) {
        fprintf(stderr, "calloc stack failed in stack.c:stack_init\n");
        return NULL;
    }
    Elem* tmp = (Elem*)calloc(5, sizeof(Elem));
    if (!tmp) {
        fprintf(stderr, "calloc data failed in stack.c:stack_init\n");
        free(st);
        return NULL;
    }
    st->data = tmp;
    st->top = -1;
    st->size = 5;
    return st;
}

static int stack_grow(stack* st) {
    int   old_size = st->size;
    int   new_size = old_size < 1024 ? 2 * old_size : 1.5 * old_size;
    Elem* tmp = (Elem*)realloc(st->data, new_size * sizeof(Elem));
    if (!tmp) {
        fprintf(stderr, "realloc data failed in stack.c:stack_grow\n");
        return -1;
    }
    st->data = tmp;
    st->size = new_size;
    return 0;
}

int stack_push(stack* st, Elem val) {
    if (st->size - 1 == st->top) {
        if (stack_grow(st)) {
            fprintf(stderr, "stack_grow failed in stack.c:stack_push\n");
            return -1;
        }
    }
    Elem new_val = (Elem)calloc(1, sizeof(Elem));
    strcpy(new_val, val);
    st->data[++st->top] = new_val;
    return 0;
}

int stack_pop(stack* st) {
    if (stack_empty(st)) {
        fprintf(stderr, "stack empty in stack.c:stack_pop\n");
        return -1;
    }
    free(st->data[st->top]);
    --st->top;
    return 0;
}

int stack_empty(stack* st) { return st->top == -1; }

int stack_destory(stack* st) {
    if (!st)
        return -1;
    for (int i = 0; i <= st->top; i++) {
        free(st->data[i]);
    }
    free(st->data);
    free(st);
    return 0;
}
